/*
 * Copyright 2010 original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alertleon;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;

/**
 * Control access to the underlying queue.
 *
 * The following configuration properties are optional for this class:
 *
 * alert.enabled=false (default: "false") - If this property is not set or is set to "false",
 *                                          all alerts will be ignored.
 * alert.excludeClass=class.path - This property can be one or more (comma-separated) class
 *                                 names. Any alerts for these classes will be ignored.
 */
public abstract class AbstractAlertQueue implements AlertQueue {

    private Log logger = LogFactory.getLog(AbstractAlertQueue.class);

    private final List<AlertListener> listeners = new ArrayList<AlertListener>();
    private final AlertConfiguration configuration;
    private Timer timer;

    public AbstractAlertQueue(AlertConfiguration configuration) {
        Assert.notNull(configuration);
        this.configuration= configuration;
        init();
    }

    private void init() {
        if (configuration.isEnabled()) {
            timer = new Timer();
            int delay = configuration.getDelay() * 60000; // Convert minutes to milliseconds.

            timer.schedule(new TimerTask() {
                    @Override
                    public void run() {

                        sendAlerts();
                    }
                }, delay, delay);
        }
    }

    public void addAlert(Class klass, String message) {
        Assert.notNull(klass);
        Assert.notNull(message);
        Assert.notNull(message);

        if (!configuration.isEnabled()) {
            return;
        }

        if (logger.isInfoEnabled()) {
            logger.info(message);
        }

        if (!isClassAlertEnabled(klass)) {

            if (logger.isWarnEnabled()) {
                logger.warn("The message is not sent because the class " + klass.getName() + " has the alert excluded.");
            }

            return;
        }

        addAlert(message);
    }

    private boolean isClassAlertEnabled(Class klass) {
        List<String> excludeClasses = configuration.getExcludeClasses();

        return excludeClasses.isEmpty() || !excludeClasses.contains(klass.getName());
    }

    public void addListener(AlertListener listener) {
        Assert.notNull(listener);
        listeners.add(listener);
    }

    public AlertConfiguration getConfiguration() {
        return configuration;
    }

    protected List<AlertListener> getListeners() {
        return listeners;
    }

    public void close() {
        if (timer != null) {
            timer.cancel();
        }
    }

    protected abstract void addAlert(String message);
}
